import NormalLevelBase from "../../Game/Base/LevelBase";
import O1HD from "../../engines/gameEngine";
import { CsvFileKind } from "../../engines/libs/CsvFileKind";
import data_control from "../../engines/libs/data_control";
import CsvDataManage from "../../engines/managers/CsvDataManage";
import level_PeopleArcheryUnitBase from "./base/level_PeopleArcheryUnitBase";
import level_peopleArcheryOption from "./unit/level_peopleArcheryOption";
import level_peopleArcheryPeople from "./unit/level_peopleArcheryPeople";
import level_peopleArcheryEnemy from "./unit/level_peopleArcheryEnemy";
import level_peopleArcheryBox from "./unit/level_peopleArcheryBox";
import level_peopleArchery_openBoxPage from "./page/level_peopleArchery_openBoxPage";
import level_peopleArchery_ResultPage from "./page/level_peopleArchery_ResultPage";
import level_PeopleArcheryBullet from "./unit/level_peopleArcheryBullet";
import mainRoot from "../../Game/MainRoot";
import { PAGE } from "../../Game/Enum";
import PageBase from "../../Game/Base/PageBase";
import { INormalLevelStruct, IInGamePagePrams } from "../../Game/Interface";
import peopleArcheryInGamePage from "../../Game/Page/peopleArcheryInGamePage";
import peopleArcheryRouGePage from "../../Game/Page/peopleArcheryRouGePage";
import peopleArcherySynthPage from "../../Game/Page/peopleArcherySynthPage";
import PeopleArcheryGetMoneyPage from "../../Game/Page/PeopleArcheryGetMoneyPage";

const {ccclass, property} = cc._decorator;

export interface peopleArcheryPeopleDataI{
    /**时间线索引 */
    timeLineIndex:number,
    /**最大生命值 */
    hp:number,
    /**攻击 */
    atk:number,
    /**攻击速度 */
    atkSpd:number,
    /**移动速度 */
    moveSpd:number,
    /**弓箭攻击距离 */
    arrowDis:number,
    /**箭的数量 */
    bulletNum:number,
}

export interface peopleArcheryGameDataI{
    /**游戏时间 */
    gameTime:number,
    /**击杀数量 */
    killNum:number,
    /**造成伤害 */
    damage:number,
}

@ccclass
export default class level_peopleArchery extends NormalLevelBase {
    @property({type:cc.Node,tooltip:"单位content"})
    /**角色content */
    unitContent:cc.Node = null;

    @property({type:cc.Prefab,tooltip:"角色预制体"})
    /**角色预制体 */
    peopleP:cc.Prefab = null;

    @property({type:cc.Prefab,tooltip:"箭的预制体"})
    /**箭预制体 */
    arrowP:cc.Prefab = null;

    @property({type:cc.Prefab,tooltip:"敌方预制体"})
    /**敌方预制体 */
    enemyP:cc.Prefab = null;

    @property({type:cc.Prefab,tooltip:"选项预制体"})
    /**选项预制体 */
    optionP:cc.Prefab = null;

    @property({type:cc.Prefab,tooltip:"箱子预制体"})
    boxPrefab:cc.Prefab = null;

    @property({type:cc.Prefab,tooltip:"开箱子预制体"})
    openBoxPagePrefab:cc.Prefab = null;

    @property({type:cc.Prefab,tooltip:"结算界面"})
    resultP:cc.Prefab = null;

    @property({type:cc.Node,tooltip:"开始游戏按钮"})
    btnStart:cc.Node = null;

    @property({type:cc.Prefab,tooltip:"扣血文本预制体"})
    subP:cc.Prefab = null;

    @property({type:cc.Node,tooltip:"touch节点"})
    touchNode:cc.Node = null;

    @property({tooltip:"是否是测试"})
    testFlag:boolean = false;

    @property({type:cc.Label,tooltip:"属性文本"})
    lbParam:cc.Label = null;

    /**角色左右移动的最小X坐标 */
    peopleMinX:number = -150;

    /**角色左右移动的最大X坐标 */
    peopleMaxX:number = 150;

    /**子弹节点池 */
    bulletPool:cc.NodePool = new cc.NodePool();

    /**游戏是否暂停 */
    gamePauseFlag:boolean = true;

    /**关卡数据 */
    peopleArcheryData:any = null;

    /**当前地图移动的总距离 */
    moveDis:number = 0;

    /**当前波次移动的距离 */
    waveDis:number = 0;

    /**当前波次 */
    realWave:number = 3;

    /**游戏时间 */
    gameTime:number = 0;

    /**造成的伤害 */
    damage:number = 0;

    /**杀敌数 */
    killCount:number = 0;

    /**当前波次 */
    curWave:number = 0;

    /**最大波次 */
    maxWave:number = 0;

    allWaves:number[] = [];

    firstFlag:boolean = true;

    /**当前角色 */
    role:level_peopleArcheryPeople = null;

    infinityFlag:boolean = false;

    infinityHpData:any = null;

    roleData:any = null;

    curMoney:number = 0;

    inGamePage:peopleArcheryInGamePage = null;

    async Init(info: INormalLevelStruct): Promise<void> {
        this.levelInfo = info;
        this.m_mode = info.mode;
        this.tips = info.tips;
        // console.warn("关卡初始化", this.levelInfo);
        let inGamePrams: IInGamePagePrams = {
            mode: this.m_mode,
            levelInfo:this.levelInfo,
            title: info.title,
            tips: info.tips,
            hideTitle: info.hideTitle
        }
        this.infinityFlag = this.levelInfo["infinityFlag"];
        this.infinityHpData = O1HD.getManagers().csvDataManager.getCsvData(CsvFileKind.CsvFile.peopleArcheryInfinityEnemyHp);
        O1HD.getManagers().soundMgr.loadSoundBundle("peopleArcherySound");
        this.roleData = O1HD.getManagers().csvDataManager.getCsvDataItem(CsvFileKind.CsvFile.peopleArcheryRole,O1HD.getManagers().peopleArcheryManager.getData().curUseRoleId);
        await this.initLevel();
        let page = await mainRoot.UISystem.OpenPage(PAGE.PEOPLE_ARCHERY_INGAME_PAGE, inGamePrams);
        (page as peopleArcheryInGamePage).bindLevel(this);
        this.inGamePage = (page as peopleArcheryInGamePage);
    }

    start(){
        if(O1HD.getServices().ossSrv.getPlatform() == "tt"){
            this.testFlag = false;
        }
    }

    async initLevel(){
        this.peopleArcheryData = O1HD.getManagers().csvDataManager.getCsvDataItem(CsvFileKind.CsvFile.peopleArcheryTimeLine,this.levelInfo.level);
        let ids:string[] = O1HD.getManagers().csvDataManager.getCsvIds(CsvFileKind.CsvFile[this.peopleArcheryData["timeLineFileName"]]);
        for(let i of ids){
            let waveData = O1HD.getManagers().csvDataManager.getCsvDataItem(CsvFileKind.CsvFile[this.peopleArcheryData["timeLineFileName"]],i);
            let enemyType:number = -1;
            let bossPro:number = Number(waveData["boss_pro"]);
            let bigPro:number = Number(waveData["big_pro"]);
            let middle_pro:number = Number(waveData["middle_pro"]);
            enemyType = Math.random() < bossPro ? 0 : enemyType;
            if(enemyType != 0){
                if(Math.random() < bigPro){
                    enemyType = 1;
                }else if(Math.random() < middle_pro){
                    enemyType = 2;
                    this.maxWave ++;
                }else{
                    enemyType = 3;
                    this.maxWave ++;
                }
            }
            this.allWaves.push(enemyType);
        }
        this.moveDis =  -Number(this.peopleArcheryData["start_dis"]);
        this.curMoney = Number(this.peopleArcheryData["complete_money"]);
        this.curWave = 0;
        this.addRole(1);
        this.createStartWave();
    }

    /**移动 */
    onTouchMoveRoleNode(e:cc.Event.EventTouch){
        if(this.gamePauseFlag){
            return;
        }
        let delta : cc.Vec2 = e.getDelta();
        let dx:number = delta.x;
        let px:number = this.role.node.x;
        if(px + dx > this.peopleMaxX){
            dx = this.peopleMaxX - px;
        }else if(px + dx < this.peopleMinX){
            dx = this.peopleMinX - px;
        }
        this.role.node.x += dx;
    }

    /**
     * 加载指定数量的角色
     * @param roleCount 需要加载的角色数量
     */
    addRole(roleCount:number){
        for(let i = 0;i<roleCount;i++){
            let role:cc.Node = cc.instantiate(this.peopleP);
            let rs = role.getComponent(level_peopleArcheryPeople);
            this.role = rs;
            this.initRoleData(role);
            this.oneUnitBindLevel(rs);
            role.setParent(this.unitContent);
            role.setPosition(0,300);
            this.touchNode.on('touchmove',this.onTouchMoveRoleNode,this);
        }
    }

    initRoleData(role:cc.Node){
        let fileName = this.roleData["role_file"];
        let level = O1HD.getManagers().peopleArcheryManager.getRoleData(this.roleData.role_id).level;
        let data = O1HD.getManagers().csvDataManager.getCsvDataItem(`config/csv/peopleArchery/role/${fileName}`,level);
        console.log("角色数据：",data);
        let rs = role.getComponent(level_peopleArcheryPeople);
        rs.minArrowDis = Number(this.peopleArcheryData["min_arrowDis"]);
        rs.maxArrowDis = Number(this.peopleArcheryData["max_arrowDis"]);
        rs.minAtkSpd = Number(this.peopleArcheryData["min_atk_spd"]);
        rs.maxAtkSpd = Number(this.peopleArcheryData["max_atk_spd"]);
        rs.minAtk = Number(this.peopleArcheryData["min_atk"]);
        rs.maxHp = Number(data["hp"]);
        rs.hp = Number(data["hp"]);
        rs.atk = Number(data["atk"]); // + O1HD.getManagers().peopleArcheryManager.getData().atkAddition;
        rs.atkSpd = Number(this.peopleArcheryData["initAtkSpd"]);
        rs.moveSpd = Number(this.peopleArcheryData["initMoveSpd"]);
        rs.arrowDis = Number(this.peopleArcheryData["initArrowDis"]);
        rs.bulletNum = Number(this.peopleArcheryData["init_arrowNum"]);
        rs.atkAddition = Number(this.peopleArcheryData["atk_addition"]);
        rs.strikeRecover = Number(this.peopleArcheryData["strike_recover"]);
        rs.hpBenefit = Number(this.peopleArcheryData["hp_benefit"]);
        rs.revitAlize = Number(this.peopleArcheryData["revit_alize"]); // + O1HD.getManagers().peopleArcheryManager.getData().revitAlize;

        let active_Talent = data["active_Talent"];
        let activeTalent = O1HD.getManagers().csvDataManager.getCsvDataItem(CsvFileKind.CsvFile.peopleArcheryTalent,active_Talent);
        let activeFile = activeTalent["talent_file"];
        let activeData = O1HD.getManagers().csvDataManager.getCsvDataItem(`config/csv/peopleArchery/talent/${activeFile}`,level);

        // 激活主动技能
        let activeTypes:string[] = activeData["param_type"].split("|");
        let activeParams:string[] = activeData["param_num"].split("|");
        for(let i=0;i<activeTypes.length;i++){
            let data = {param_type:activeTypes[i],option_param:activeParams[i]}
            this.parseDataAddPeople(data);
        }
        
        //激活被动技能
        let peoples = O1HD.getManagers().peopleArcheryManager.getData().unlockRole;
        for(let people of peoples){
            let pId = people.id;
            let pLevel = people.level;
            let roleData = O1HD.getManagers().csvDataManager.getCsvDataItem(CsvFileKind.CsvFile.peopleArcheryRole,pId);
            let rFileName = roleData["role_file"];
            let rData = O1HD.getManagers().csvDataManager.getCsvDataItem(`config/csv/peopleArchery/role/${rFileName}`,level);
            let passive_Talent = rData["passive_Talent"];
            let passiveTalent = O1HD.getManagers().csvDataManager.getCsvDataItem(CsvFileKind.CsvFile.peopleArcheryTalent,passive_Talent);
            let passiveFile = passiveTalent["talent_file"];
            let passiveData = O1HD.getManagers().csvDataManager.getCsvDataItem(`config/csv/peopleArchery/talent/${passiveFile}`,pLevel);
            let passiveTypes:string[] = passiveData["param_type"].split("|");
            let passiveParams:string[] = passiveData["param_num"].split("|");
            for(let i =0;i<passiveTypes.length;i++){
                let data = {param_type:passiveTypes[i],option_param:passiveParams[i]}
                this.parseDataAddPeople(data);
            }
        }
        //测试数据
        // rs.criticalPro = 0.5;
        // rs.criticalAddition = 1.5;
        // rs.shotLeech = 0.2;
        // rs.maxHpAddition = 0.2;
        // rs.revitalizeAddition = 0.2;
        // rs.reduceDamage = 0.2;
        // rs.bossHpReduce = 0.2;
        // rs.revitalizePercent = 0.2;
        // rs.bossDeathRevitalizePercent = 0.2;


    }

    oneUnitBindLevel(unit:level_PeopleArcheryUnitBase){
        unit.bindLevel(this);
    }

    /**获取一个子弹节点 */
    getOneBullet(){
        let bullet:cc.Node = null;
        if(this.bulletPool.size() > 0){
            bullet = this.bulletPool.get();
        }else{
            bullet = cc.instantiate(this.arrowP);
        }
        return bullet;
    }

    update(dt:number){
        if(this.testFlag  && this.role){
            this.lbParam.string = `
            最大血量：${this.role.maxHp}
            血量：${this.role.hp}
            攻速：${this.role.atkSpd}
            攻击力：${this.role.atk}
            永久攻击：${O1HD.getManagers().peopleArcheryManager.getData().atkAddition}
            撞击回复：${this.role.strikeRecover}
            血量收益：${this.role.hpBenefit}
            每两秒回血：${this.role.revitAlize}
            攻击加成：${this.role.atkAddition}
            伤害减免： ${this.role.reduceDamage}
            暴击率：${this.role.criticalPro}
            暴击伤害：${this.role.criticalAddition}
            血量上限：${this.role.maxHpAddition}
            回血增强：${this.role.revitalizeAddition}
            boss血量降低：${this.role.bossHpReduce}
            每五秒回复血量：${this.role.revitalizePercent}
            射击吸血：${this.role.shotLeech}
            金币加成：${this.role.goldAddition}
            击败boss回血：${this.role.bossDeathRevitalizePercent}
            `;
        }
        if(this.gamePauseFlag){
            return;
        }
        let moveSpeed:number = this.getRoleMoveSpd();
        let moveDis:number = moveSpeed * dt;
        this.moveDis += moveDis;
        this.waveDis += moveDis;
        this.gameTime += dt;
        if(this.waveDis >= this.peopleArcheryData["oneWaveDis"]){
            this.waveDis = 0;
            // 创建一波
            this.createOneWave(this.realWave);
            this.realWave ++;
        }
    }

    //创建开始波次
    createStartWave(){
        for(let i = 0;i<this.realWave;i++){
            this.createOneWave(i);
        }
    }

    createOneWave(waveIndex:number){
        let ids:string[] = O1HD.getManagers().csvDataManager.getCsvIds(CsvFileKind.CsvFile[this.peopleArcheryData["timeLineFileName"]]);
        if(this.realWave >= ids.length){
            return;
        }
        let lastWaveFlag:boolean = false;
        if(this.realWave == ids.length -1){
            lastWaveFlag = true;
        }
        let waveData = O1HD.getManagers().csvDataManager.getCsvDataItem(CsvFileKind.CsvFile[this.peopleArcheryData["timeLineFileName"]],waveIndex + 1);
        let waveInterval:number =Number(this.peopleArcheryData["oneWaveDis"]);
        let maxY:number = (waveIndex + 1) * waveInterval;
        let minY:number = maxY - waveInterval;
        let addY:number = minY - this.moveDis;

        let posAry:cc.Vec2[] = data_control.randomSortArray([cc.v2(this.peopleMinX,waveInterval * 0.4),cc.v2(this.peopleMaxX,waveInterval * 0.4),cc.v2(this.peopleMinX,waveInterval * 0.6),cc.v2(this.peopleMaxX,waveInterval * 0.6)]);
        let posCopy:cc.Vec2[] = [];
        let enemyNum:number = Number(waveData["enemy_num"]);

        let num = Math.random() < enemyNum % 1 ? 1 : 0;
        let realNum:number = Math.floor(enemyNum) + num;
        let hasOption:boolean = true;
        let enemyType:number = -1;
        let enemyHp:number = Number(waveData["wave_hp"]);
        if(this.infinityFlag){
            let infinityWaveData = Number(this.infinityHpData[waveIndex + 1][this.infinityHpData["title"][`enemyHp_${O1HD.getManagers().peopleArcheryManager.getData().curInfinityLevel}`]]);
            enemyHp = Number(infinityWaveData);
        }
        let hpRatio:number = 0;
        let boss_hp_reduce:number = 0;
        enemyType = this.allWaves[waveIndex];
        switch(enemyType){
            case 0:{
                posAry = data_control.randomSortArray([cc.v2(0,waveInterval)]);
                realNum = 1;
                hasOption = false;
                hpRatio = Number(this.peopleArcheryData["boss_hp_ratio"]);
                boss_hp_reduce = this.role.bossHpReduce;
                break;
            }
            case 1:{
                hasOption = false;
                posAry = data_control.randomSortArray([cc.v2(0,waveInterval)]);
                hpRatio = Number(this.peopleArcheryData["big_hp_ratio"]);
                boss_hp_reduce = this.role.bossHpReduce;
                break;
            }
            case 2:{
                hpRatio = Number(this.peopleArcheryData["middle_hp_ratio"]);
                break;
            }
            case 3:{
                hpRatio = Number(this.peopleArcheryData["small_hp_ratio"]);
                break;
            }
        }
        posCopy = posAry.concat();
        for(let i = 0;i < realNum; i++){
            if(posAry.length < 1){
                posAry = posCopy.concat();
            }

            switch(enemyType){
                case 2:
                case 3:{
                    let pro = waveData["middle_pro"];
                    if(Math.random() < pro){
                        hpRatio = Number(this.peopleArcheryData["middle_hp_ratio"]);
                        enemyType = 2;
                    }else{
                        hpRatio = Number(this.peopleArcheryData["small_hp_ratio"]);
                        enemyType = 3;
                    }
                    break;
                }
            }

            let pos:cc.Vec2 = posAry.pop();
            pos.y += addY;
            let enemyNode = cc.instantiate(this.enemyP);
            let es = enemyNode.getComponent(level_peopleArcheryEnemy);
            this.oneUnitBindLevel(es);
            es.bindType(enemyType,lastWaveFlag,waveData);
            let hp:number = enemyHp * hpRatio;
            // if(enemyType == 0 || enemyType == 1){
            //     console.log(hp,"原有血量");
            // }
            hp -= hp * boss_hp_reduce;
            // if(enemyType == 0 || enemyType == 1){
            //     console.log(hp,"现有血量");
            // }
            es.maxHp = hp;
            es.hp = hp;
            enemyNode.setParent(this.unitContent);
            enemyNode.setPosition(pos);
        }

        if(hasOption){
            let nowWaveOptionType:string = waveData["option_Type"];
            let optionNodes:cc.Node[] = [];
            let firstFlag:boolean = this.firstFlag;
            let roleProfile:string = this.role.profile;
            let createOptionsCount:number = roleProfile != "0" && nowWaveOptionType == "1" ? 1 : 2;
            let optionStr:string = waveData.arise_options;
            let optionWeightStr:string = waveData.arise_options_weight;
            let surviveCatastropheData = null;
            switch(nowWaveOptionType){
                case "1":{
                    switch(roleProfile){
                        case "1":{
                            optionStr = waveData.fairy_arise_options;
                            optionWeightStr = waveData.fairy_arise_weight;
                            break;
                        }
                        case "2":{
                            optionStr = waveData.magic_arise_options;
                            optionWeightStr = waveData.magic_arise_weight;
                            break;
                        }
                    }
                    break;
                }
                case "2":{
                    let surviveCatastropheIds = O1HD.getManagers().csvDataManager.getCsvIds(CsvFileKind.CsvFile.peopleArcherySurviveCatastrophe);
                    let randId = data_control.getRandItemOfArray(surviveCatastropheIds);
                    surviveCatastropheData = O1HD.getManagers().csvDataManager.getCsvDataItem(CsvFileKind.CsvFile.peopleArcherySurviveCatastrophe,randId);
                    break;
                }
            }
            
            let ariseOptions:string[] = [];
            let optionPos:cc.Vec2[] = [cc.v2(this.peopleMinX,maxY - this.moveDis),cc.v2(this.peopleMaxX,maxY - this.moveDis)]; //data_control.randomSortArray([cc.v2(this.peopleMinX,maxY - this.moveDis),cc.v2(this.peopleMaxX,maxY - this.moveDis)]);
            for(let i = 0;i<createOptionsCount;i++){
                switch(nowWaveOptionType){
                    case "1":{
                        if(this.role.profile == "0"){
                            if( i == 0){
                                optionStr = waveData.fairy_arise_options;
                                optionWeightStr = waveData.fairy_arise_weight;
                            }else{
                                optionStr = waveData.magic_arise_options;
                                optionWeightStr = waveData.magic_arise_weight;
                            }
                        }
                        break;
                    }
                    case "2":{
                        if(i==0){
                            optionStr = surviveCatastropheData.surviveCatastrophe_one_option;
                            optionWeightStr = surviveCatastropheData.surviveCatastrophe_one_option_weight;
                        }else{
                            optionStr = surviveCatastropheData.surviveCatastrophe_two_option;
                            optionWeightStr = surviveCatastropheData.surviveCatastrophe_two_option_weight;
                        }   
                        break;
                    }
                }
                let optionTypes:string[] = optionStr.split("|");
                let weightAry:number[] = optionWeightStr.split("|").map((value)=>{
                    let v = Number(value);
                    return v;
                });
                let weightIndex:number = data_control.getRandIPosByWeights(weightAry);
                let optionType:string = optionTypes[weightIndex];
                let optionData = O1HD.getManagers().csvDataManager.getCsvDataItem(CsvFileKind.CsvFile.peopleArcheryOptionDoor,optionType);
                let optionAry:string[] = optionData.option_door_arise_type.split("|");
                let randO = data_control.getRandItemOfArray(optionAry);
                let optionTypeAry:string[] = randO.split("&");


                if(optionAry.length >= 2){
                    optionTypeAry = optionAry[i].split("&");
                }
                let randType = data_control.getRandItemOfArray(optionTypeAry);
                let optionsAry = this.getPeopleArcheryOptions(randType);
                let randData = data_control.getRandItemOfArray(optionsAry);
                while(ariseOptions.includes(randData["optionId"])){
                    randType = data_control.getRandItemOfArray(optionTypeAry);
                    optionsAry = this.getPeopleArcheryOptions(randType);
                    randData = data_control.getRandItemOfArray(optionsAry);
                }
                let curOptionType:string = "0";
                switch(nowWaveOptionType){
                    case "1":{
                        if(this.role.profile == "0"){
                            curOptionType = (i + 1).toString();
                            this.firstFlag = false;
                        }else{
                            curOptionType = this.role.profile;
                            optionPos = [];
                            optionPos[0] = cc.v2(0,maxY - this.moveDis);
                        }
                        break;
                    }
                }

                ariseOptions.push(randData["optionId"]);
                let randPos:cc.Vec2 = optionPos[i];
                let option = cc.instantiate(this.optionP);
                let optionScript :level_peopleArcheryOption = option.getComponent(level_peopleArcheryOption);
                this.oneUnitBindLevel(optionScript);
                optionScript.bindData(randData,lastWaveFlag,curOptionType,firstFlag,i,waveData,surviveCatastropheData);
                optionNodes.push(option);
                option.setPosition(randPos);
                option.setParent(this.unitContent);
            }
            for(let option of optionNodes){
                let os = option.getComponent(level_peopleArcheryOption);
                os.groupOption = optionNodes;
            }
        }
    }

    getOptions(optionStr:string,length:number){
        let optionAry:string[] = optionStr.split("|");
        let ariseOptions:string[] = [];
        let options:any[] = [];
        for(let i = 0;i<length;i++){
            let randType = data_control.getRandItemOfArray(optionAry);
            let optionsAry = this.getPeopleArcheryOptions(randType);
            let randData = data_control.getRandItemOfArray(optionsAry);
            while(ariseOptions.includes(randData["optionId"])){
                randType = data_control.getRandItemOfArray(optionAry);
                optionsAry = this.getPeopleArcheryOptions(randType);
                randData = data_control.getRandItemOfArray(optionsAry);
            }
            ariseOptions.push(randData["optionId"]);
            options.push(randData);
        }
        return options;
    }

    /**
     * 
     * @param type 
     * @returns 
     */
    getPeopleArcheryOptions(type:string){
        let ids = O1HD.getManagers().csvDataManager.getCsvIds(CsvFileKind.CsvFile.peopleArcheryOption);
        let datas :any[] = [];
        for(let id of ids){
           let data = O1HD.getManagers().csvDataManager.getCsvDataItem(CsvFileKind.CsvFile.peopleArcheryOption,id);
           if(data.option_type == type){
                datas.push(data);
           }
        }
        return datas;
    }

    /**
     * 解析数据并加到角色身上
     */
    parseDataAddPeople(data:any){
        let type =data?.param_type;
        let param =  Number(data?.option_param);
        switch(type){
            /**生命值 */
            case "0":{
                let hp = this.role.hp;
                let maxHp = this.role.realMaxHp;
                let hpAddition:number = param;
                let maxHpAddition:number = param;
                if(param > 0){
                    hpAddition = Math.floor(param * this.role.hpBenefit);
                    maxHpAddition = Math.floor(param * this.role.hpBenefit);
                }

                let additionFlag:boolean  =  data["additionFlag"] == false ? false: true;

                if(data["reCoverMaxHp"] != "0"){
                    this.role.maxHp = maxHp + (additionFlag ? maxHpAddition : 0);
                }
                this.role.hp = hp + (additionFlag ? hpAddition : 0 );
                if(param > 0){  
                    this.role.addHpAni();
                }
                if(this.role.hp <= 0){
                    this.role.unitDeath();
                }
                if(data["reCoverMaxHp"] != "0"){
                    data.option_param = hpAddition.toString();
                    this.roleAddParamLb(data);
                }

                // console.log("初始血量：",hp,"最大血量：",this.role,maxHp,"血量加成：",hpAddition,"最大血量加成：",maxHpAddition);
                return;
                break;
            }
            /**攻击力 */
            case "1":{
                let atk = this.role.atk;
                this.role.atk = atk + param;
                break;
            }
            /**攻击速度 */
            case "2":{
                let atkSpd = this.role.initAtk;
                let addition = atkSpd * param;
                this.role.atkSpdAdd += addition;
                break;
            }
            /**箭的攻击距离 */
            case "3":{
                let arrowDis = this.role.arrowDis;
                this.role.arrowDis = arrowDis + param;
                break;
            }
            /**箭的数量 */
            case "4":{
                let arrowNum = this.role.bulletNum;
                this.role.bulletNum = arrowNum + param;
                break;
            }
            /**地图移动速度 */
            case "5":{
                let moveSpd = this.role.moveSpd;
                this.role.moveSpd = moveSpd + param;
                break;
            }
            /**永久攻击加成 */
            case "6":{
                O1HD.getManagers().peopleArcheryManager.setData({atkAddition:param},true);
                let atk = this.role.atk;
                this.role.atk = atk + param;
                break;
            }
            /**每五秒回血 */
            case "7":{
                let revitAlize:number = this.role.revitAlize;
                this.role.revitAlize = revitAlize + param;
                break;
            }
            /**射击伤害加成 */
            case "8":{
                let atkAddition:number = this.role.atkAddition;
                this.role.atkAddition = atkAddition + param;
                break;
            }
            /**血量收益 */
            case "9":{
                let hpBenefit:number = this.role.hpBenefit;
                this.role.hpBenefit = hpBenefit + param;
                let hp = this.role.hp;
                let maxHp:number = this.role.maxHp;

                let hpAddition:number = hp / hpBenefit * this.role.hpBenefit; //this.role.hpBenefit * hp - hp * hpBenefit;
                let maxHpAddition:number = maxHp / hpBenefit * this.role.hpBenefit;
                this.role.maxHp = maxHpAddition;
                this.role.hp = hpAddition;

                break;
            }
            /**撞击回血 */
            case "10":{
                let strikeRecover = this.role.strikeRecover;
                this.role.strikeRecover = strikeRecover + param;
                break;
            }
            //永久回复
            case "11":{
                let revitAlize:number = this.role.revitAlize;
                this.role.revitAlize = revitAlize + param;
                O1HD.getManagers().peopleArcheryManager.setData({revitAlize:param},true);
                break;
            }
            //伤害减免
            case "12":{
                let reduceDamage = this.role.reduceDamage;
                let reduceDamageAddition:number = reduceDamage + param;
                this.role.reduceDamage = reduceDamageAddition;
                break;
            }
            //射击暴击率
            case "13":{
                let criticalPro:number = this.role.criticalPro;
                let num:number = criticalPro + param;
                this.role.criticalPro = num;
                break;
            }
            //射击暴击伤害
            case "14":{
                let criticalAddition:number = this.role.criticalAddition;
                let num = criticalAddition + param;
                this.role.criticalAddition = num;
                break;
            }
            //血量上限加成
            case "15":{
                let maxHpAddition:number = this.role.maxHpAddition;
                let num = maxHpAddition + param;
                this.role.maxHpAddition = num;
                break;
            }
            //回血增强
            case "16":{
                let revitalizeAddition = this.role.revitalizeAddition;
                let num = revitalizeAddition + param;
                this.role.revitalizeAddition = num;
                break;
            }
            //boss血量降低
            case "17":{
                let bossHpReduce = this.role.bossHpReduce;
                let num = bossHpReduce + param;
                this.role.bossHpReduce = num;
                break;
            }
            //每五秒回复百分比血量
            case "18":{
                let revitalizePrecent = this.role.revitalizePercent;
                let num = revitalizePrecent + param;
                this.role.revitalizePercent = num;
                break;
            }
            //射击吸血
            case "19":{
                let shotLeech:number = this.role.shotLeech;
                let num = shotLeech + param;
                this.role.shotLeech = num;
                break;
            }
            //金币加成
            case "20":{
                let addition:number = this.role.goldAddition;
                let num = addition + param;
                this.role.goldAddition = num;
                break;
            }
            //boss死亡回复百分比血量
            case "21":{
                let addition:number = this.role.bossDeathRevitalizePercent;
                let num = addition + param;
                this.role.bossDeathRevitalizePercent = num;
                break;
            }
            case "22":{
                let addition2:number = this.role.atkAddition2;
                let num = addition2 + param;
                this.role.atkAddition2 = num;
                break;
            }
        }
        if(data){
            this.roleAddParamLb(data);
        }
    }

    getRoleMoveSpd(){
        return this.role?.moveSpd || 0;
    }

    createOneBox(enemy:level_peopleArcheryEnemy){
        let pos:cc.Vec2 = enemy.node.getPosition();
        let data = enemy.waveData;
        let box = cc.instantiate(this.boxPrefab);
        let bs = box.getComponent(level_peopleArcheryBox);
        this.oneUnitBindLevel(bs);
        bs.bindData(enemy.enemyType,data);
        box.setParent(this.unitContent);
        box.setPosition(pos);
    }


    openBoxPage(datas:any[],lastWaveFlag:boolean){
        let page:cc.Node = cc.instantiate(this.openBoxPagePrefab);
        let ps = page.getComponent(level_peopleArchery_openBoxPage);
        let completeFun = lastWaveFlag ? ()=>{this.gameWin()} : null;
        ps.bindData(datas,this,completeFun);
        page.setParent(this.node);
    }

    async openMoneyPage(winFlag:boolean = true){
        let page = await mainRoot.UISystem.OpenPage(PAGE.PEOPEL_ARCHERY_GET_MONEY_PAGE);
        let getMoneyPage = page as PeopleArcheryGetMoneyPage;
        this.gamePauseFlag = true;
        getMoneyPage.bindLevel(this,this.curMoney,()=>{if(winFlag){
            this.gameWin();
        }else{
            this.gameFail();
        }
    })
    }

    async openRouGePage(){
        let page = await mainRoot.UISystem.OpenPage(PAGE.PEOPLE_ARCHERY_ROUGE);
        (page as peopleArcheryRouGePage).bindLevel(this);
    }

    /**游戏失败 */
    async gameFail(){
        this.gamePauseFlag = true;
        let page : PageBase = await mainRoot.UISystem.OpenPage(PAGE.LEVEL_PEOPLE_ARCHERY_RESULTPAGE,{mode:this.levelInfo.mode});
        (page  as level_peopleArchery_ResultPage).bindData(this,false);
        this.destroyOneTypeUnit("bullet");
    }

    /**游戏胜利 */
    async gameWin(){
        this.gamePauseFlag = true;
        mainRoot.LevelSystem.AddLevel(this.m_mode);
        let page : PageBase = await mainRoot.UISystem.OpenPage(PAGE.LEVEL_PEOPLE_ARCHERY_RESULTPAGE,{mode:this.levelInfo.mode});
        if(this.infinityFlag && O1HD.getManagers().peopleArcheryManager.getData().infinityLevel == O1HD.getManagers().peopleArcheryManager.getData().curInfinityLevel &&   O1HD.getManagers().peopleArcheryManager.getData().infinityLevel < Object.keys((O1HD.getManagers().csvDataManager.getCsvData(CsvFileKind.CsvFile.peopleArcheryInfinityEnemyHp)["title"])).length - 1){
            O1HD.getServices().miniGameSrv.getAppApiInstance().commitRank(O1HD.getManagers().peopleArcheryManager.getData().infinityLevel + 1);
            O1HD.getManagers().peopleArcheryManager.setData({infinityLevel:1},true);
        }
        O1HD.getManagers().peopleArcheryManager.setData({curInfinityLevel:1},true);
        // O1HD.getManagers().peopleArcheryManager.setData({money:this.curMoney},true);
        (page  as level_peopleArchery_ResultPage).bindData(this,true);
        this.destroyOneTypeUnit("bullet");
    }

    /**角色复活 */
    peopleAlive(){
        this.role.alive();
        this.gamePauseFlag = false;
    }

    onBtnStart(e:cc.Event.EventTouch){
        this.btnStart.active = false;
        this.gamePauseFlag = false;
    }

    /**
     * 销毁除了角色之外的所有单位
     */
    destroyAllUnit(){
        this.role.node.removeFromParent(false);
        this.unitContent.children.forEach((n:cc.Node)=>{
            let ns = n.getComponent(level_PeopleArcheryUnitBase);
            ns.unitDestroy();
        });
        this.role.node.setParent(this.unitContent);
    }

    /**
     * 销毁指定类型的所有单位
     * @param type 
     */
    destroyOneTypeUnit(type:string){
        let c = null;
        switch(type){
            case "bullet":{
                c = level_PeopleArcheryBullet;
                break;
            }
            case "option":{
                c = level_peopleArcheryOption;
                break;
            }
            case "enemy":{
                c = level_peopleArcheryEnemy;
                break;
            }
            case "box":{
                c = level_peopleArcheryBox;
                break;
            }
        }
        let unitAry:any[] = [];
        this.unitContent.children.forEach((n:cc.Node)=>{
            let ns = n.getComponent(c);
            if(ns){
                unitAry.push(ns);
            }
        });
        for(let k of unitAry){
            k.getComponent(c).unitDestroy();
        }

    }

    /**初始化游戏 */
    initGameData(){
        this.killCount = 0;
        this.gameTime = 0;
        this.damage = 0;
        this.waveDis = 0;
        this.realWave = 3;
        this.moveDis = 0;
        this.destroyAllUnit();
    }

    onDestroy(){
        this.bulletPool.clear();    
    }
    
    /** 受伤扣血文本 */
    addSubLb(subNum:number,targetNode:cc.Node,criticalFlag:boolean){
        if(criticalFlag != null && !criticalFlag){
            return;
        }
        let node:cc.Node = cc.instantiate(this.subP);
        let baoji:cc.Node = node.getChildByName("baoji");
        baoji.active = criticalFlag != null && criticalFlag;
        let nLb:cc.Label = node.getComponent(cc.Label);
        nLb.string = `-${subNum}`;
        node.color = criticalFlag != null && criticalFlag ? cc.Color.RED: cc.color(231,114,63);
        node.setParent(this.unitContent);
        node.setPosition(targetNode.position.x,targetNode.position.y + 20);
        cc.tween(node).by(0.5,{y:50,opacity:0}).call(()=>{
            node.destroy();
            node.removeFromParent();
        }).start();
    }

    /**角色增加属性文本 */
    roleAddParamLb(data:any){
        let targetNode:cc.Node = this.role.node;
        let node:cc.Node = cc.instantiate(this.subP);
        let nLb:cc.Label = node.getComponent(cc.Label);
        nLb.string = O1HD.getManagers().peopleArcheryManager.getOptionText(data);
        node.setParent(this.unitContent);
        node.setPosition(targetNode.position.x,targetNode.position.y + 20);
        cc.tween(node).by(0.5,{y:10,opacity:0}).call(()=>{
            node.destroy();
            node.removeFromParent();
        }).start();
    }

    /**给角色加一件武器 */
    roleAddWeapon(weaponId:string){
        let weaponData = O1HD.getManagers().csvDataManager.getCsvDataItem(CsvFileKind.CsvFile.peopleArcheryMagicWeapon,weaponId);
        let param = weaponData["param"];
        let pAry:string[] = param.split("&");
        let typeAry:string[] = [];
        let paramAry:number[] = [];
        pAry.forEach((p:string)=>{
            let strAry:string[] = p.split("|");
            typeAry.push(strAry["0"]);
            paramAry.push(Number(strAry["1"]));
        });
        for(let i:number = 0; i<typeAry.length; i++){
            let data = {param_type:typeAry[i],option_param:paramAry[i]};
            this.parseDataAddPeople(data);
        }
        this.role.addOneWeapon(weaponId);
        this.inGamePage.refrenshWeaponContent();
    }

    /**
     * 杀死一个敌方单位
     * @param type 敌方单位类型
     */
    killOneEnemy(type:number){
        switch(type){
            case 0:{
                this.curMoney += Number(this.peopleArcheryData["kill_boss_money"]);
                break;
            }
            case 1:{
                this.curMoney += Number(this.peopleArcheryData["kill_big_money"]);
                break;
            }
            case 2:{
                this.curMoney += Number(this.peopleArcheryData["kill_middle_money"]);
                break;
            }
            case 3:{
                this.curMoney += Number(this.peopleArcheryData["kill_small_money"]);
                break;
            }
        }
        console.log(this.curMoney);
    }

    async openSynthPage(weaponId:string,oneWeaponId:string,twoWeaponId:string){
        let page = await mainRoot.UISystem.OpenPage(PAGE.PEOPLE_ARCHERY_SYNTH_PAGE);
        let synthPage:peopleArcherySynthPage = (page as peopleArcherySynthPage);
        synthPage.bindLevel(this,weaponId,oneWeaponId,twoWeaponId);
    }

}
